package org.tnc.budget.webapp.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.tnc.budget.model.AttachmentTable;
import org.tnc.budget.model.BudgetCenter;
import org.tnc.budget.model.EventTable;
import org.tnc.budget.service.BudgetManager;
import org.tnc.budget.service.EventManager;
import org.tnc.model.User;
import org.tnc.service.UserManager;
import org.tnc.webapp.controller.MessageBaseController;

/**
 * 用户查询自己的约会
 * 
 * @author houjj | 2011-4-5 上午10:40:12
 */
@Controller
public class UserEventController extends MessageBaseController {

	@SuppressWarnings("unused")
	private Logger log = Logger.getLogger(UserEventController.class);

	public void setUserManager(UserManager userManager) {
		this.userManager = userManager;
	}

	private EventManager eventManager;

	private UserManager userManager;

	private BudgetManager budgetManager;

	private User getLoginUser() {
		return (User) SecurityContextHolder.getContext().getAuthentication()
				.getPrincipal();
	}

	public static String getFirstDayThisMonth() {
		Calendar c = Calendar.getInstance();
		c.set(Calendar.DAY_OF_MONTH, 1);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		return sdf.format(c.getTime());
	}

	public static String getLastDayThisMonth() {
		Calendar c = Calendar.getInstance();
		c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		return sdf.format(c.getTime());
	}

	@RequestMapping("/configAdmin.html")
	public String configAdmin(ModelMap model) {

		int autoReviewDOM = eventManager.getAutoReviewDayOfMonth();
		model.put("auto_review_day_of_month", "" + autoReviewDOM);

		return "admin/config";
	}

	@RequestMapping("/setConfig.html")
	public String setConfig(HttpServletRequest request, @RequestParam("key")String key, @RequestParam("value")String value) {
		if (key != null && value != null) {
			if ("auto_review_day_of_month".equals(key)) {
				int dom = Integer.parseInt(value);
				if (dom > Calendar.getInstance().getMaximum(Calendar.DAY_OF_MONTH)) {
					saveError(request, "取值超出范围（1~31）");
				}else {
					eventManager.setAutoReviewDayOfMonth(dom);
				}
			}
		}
		return "redirect:/configAdmin.html";
	}

	@RequestMapping("/event/deleteMyEvent.html")
	public String deleteEvent(@RequestParam("id") String eventId, HttpSession session) {
		
		if (eventId != null && eventId.length() != 0) {
			
			eventManager.deleteEventById(Integer.parseInt(eventId));
			
		}
		
		return "redirect:/event/findEvents.html?startTime="+session.getAttribute("startTime") + "&endTime=" + session.getAttribute("endTime");
	}
	
	@RequestMapping("/event/bcMgrReview.html")
	public void bcManagerReview(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		String username = request.getParameter("username");
		if (username != null) {
			String startTime = request.getParameter("startTime");
			String endTime = request.getParameter("endTime");
			String bcId = request.getParameter("bcId");
			List<EventTable> events = eventManager.findUserEventsByTimeAndBC(
					startTime, endTime, Integer.parseInt(bcId));
			List<Integer> reviewed = new LinkedList<Integer>();
			for (EventTable eventTable : events) {
				if (eventTable.getIsReviewed() == null
						|| !eventTable.getIsReviewed()) {
					eventTable.setIsReviewed(true);
					eventTable.setIsPassed(true);
					eventManager.updateEventTable(eventTable);
					reviewed.add(eventTable.getId());
				}
			}
			response.getWriter().append(StringUtils.join(reviewed, ','));
		} else {
			String eventId = request.getParameter("eventId");
			if (eventId != null) {
				Integer eid = Integer.parseInt(eventId);
				EventTable et = eventManager.getEventById(eid);
				if (et != null) {
					String _remark = request.getParameter("remark");
					String _passed = request.getParameter("passed");
					boolean passed = Boolean.parseBoolean(_passed);
					et.setIsPassed(passed);
					et.setReviewRemarks(_remark);
					et.setIsReviewed(true);
					eventManager.updateEventTable(et);
					if (!passed) {
						// @TODO send email.
						userManager.sendEmailTo(
								"您在预算中心" + et.getBudgetCenter().getBcName()
										+ "的部分工作未通过预算中心经理审批",
								""
										+ et.getBudgetCenter().getUser()
												.getFullName() + ": " + _remark
										+ "\n" + "日期：" + et.getStartDate()
										+ " " + et.getStartTime() + "~"
										+ et.getEndTime() + "\n" + "主题："
										+ et.getEventName(),
								et.getUser(),
								userManager.getUser(et.getUser().getParentId()
										.toString()));
					}
					response.getWriter().append(eventId);
				}
			}
		}
	}

	@SuppressWarnings("unchecked")
	@RequestMapping("/event/all.html")
	public String allManager(
			@RequestParam(value = "startTime", required = false) String startTime,
			@RequestParam(value = "endTime", required = false) String endTime,
			@RequestParam(value = "bcId", required = false) Integer bcId,
			@RequestParam(value = "userId", required = false) Long[] userId,
			ModelMap model) {

		List<User> users = userManager.getUsers();
		model.put("users", users);

		List<BudgetCenter> bclist = budgetManager.getAll();

		if (startTime == null) {
			startTime = getFirstDayThisMonth();
		}
		if (endTime == null) {
			endTime = getLastDayThisMonth();
		}
		if (userId != null && userId.length > 0)
			model.put("selectedUserId",
					new HashSet<Long>(Arrays.asList(userId)));
		model.put("bcList", bclist);
		model.put("startTime", startTime);
		model.put("endTime", endTime);
		model.put("bcId", bcId);

		List<EventTable> events = eventManager.findUserEvents(startTime,
				endTime, bcId, userId);
		model.put("events", events);

		return "/event/allManager";
	}

	@SuppressWarnings("unchecked")
	@RequestMapping("/event/bcManager.html")
	public String bcManager(
			@RequestParam(value = "startTime", required = false) String startTime,
			@RequestParam(value = "endTime", required = false) String endTime,
			@RequestParam(value = "bcId", required = false) Integer bcId,
			ModelMap model) {

		List<BudgetCenter> bcList = budgetManager.findByDuty(getLoginUser()
				.getId());

		if (startTime == null) {
			startTime = getFirstDayThisMonth();
		}
		if (endTime == null) {
			endTime = getLastDayThisMonth();
		}

		if (bcId == null && !bcList.isEmpty()) {
			bcId = bcList.get(0).getId();
		}

		model.put("bcList", bcList);
		model.put("startTime", startTime);
		model.put("endTime", endTime);

		if (bcId != null) {
			model.put("bcId", bcId);
			List<EventTable> events = eventManager.findUserEventsByTimeAndBC(
					startTime, endTime, bcId);

			Map<String, User> userNames = new HashMap<String, User>();
			Map<String, Double> hours = new LinkedHashMap<String, Double>();
			Map<String, Integer> passed = new LinkedHashMap<String, Integer>();
			Map<String, Integer> reject = new LinkedHashMap<String, Integer>();
			Map<String, Integer> pending = new LinkedHashMap<String, Integer>();
			Map<String, List<EventTable>> userDetails = new LinkedHashMap<String, List<EventTable>>();

			for (EventTable et : events) {
				String user = et.getUser().getUsername();
				userNames.put(user, et.getUser());

				Double th = hours.get(user);
				if (th == null)
					th = et.getDuration();
				else
					th += et.getDuration();
				hours.put(user, th);

				Integer p = passed.get(user);
				Integer r = reject.get(user);
				Integer w = pending.get(user);
				if (p == null) {
					p = 0;
				}
				if (r == null) {
					r = 0;
				}
				if (w == null) {
					w = 0;
				}
				if (et.getIsReviewed() == null || !et.getIsReviewed()) {
					w++;
				} else {
					if (et.getIsPassed() == null || !et.getIsPassed()) {
						r++;
					} else {
						p++;
					}
				}
				reject.put(user, r);
				pending.put(user, w);
				passed.put(user, p);

				List<EventTable> userEvents = userDetails.get(user);
				if (userEvents == null) {
					userEvents = new LinkedList<EventTable>();
					userDetails.put(user, userEvents);
				}
				userEvents.add(et);
			}

			model.put("userNames", userNames);
			model.put("userDetails", userDetails);
			model.put("hours", hours);
			model.put("events", events);
			model.put("passed", passed);
			model.put("reject", reject);
			model.put("pending", pending);
		}

		return "/event/bcManager";
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@RequestMapping(value = "/event/projectManager.html")
	public String projectManagerQueryForm(
			@RequestParam(value = "startTime", required = false) String startTime,
			@RequestParam(value = "endTime", required = false) String endTime,
			@RequestParam(value = "userId", required = false) Long[] userId,
			ModelMap map) {

		User u = getLoginUser();

		if (StringUtils.isBlank(u.getProject())) {
			return "/event/projectManager";
		}

		List<User> users = userManager.getUsersBySupervisor(u);
		map.put("users", users);
		map.put("pm", u);

		if (StringUtils.isNotBlank(startTime)
				&& StringUtils.isNotBlank(endTime)) {
			// Whatever... may be changed to isBlank() || isBlank().
		} else {
			Calendar start = Calendar.getInstance();
			start.set(Calendar.DAY_OF_MONTH, 1);
			Calendar end = Calendar.getInstance();
			end.set(Calendar.DAY_OF_MONTH,
					end.getActualMaximum(Calendar.DAY_OF_MONTH));

			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			startTime = sdf.format(start.getTime());
			endTime = sdf.format(end.getTime());
		}

		map.put("startTime", startTime);
		map.put("endTime", endTime);

		if (userId == null || userId.length == 0 || userId[0] == null) {
			userId = new Long[users.size()];
			int i = 0;
			for (Iterator iterator = users.iterator(); iterator.hasNext();) {
				User user = (User) iterator.next();
				userId[i++] = user.getId();
			}
		}

		map.put("selectedUserId", new HashSet<Long>(Arrays.asList(userId)));

		List<EventTable> events = this.eventManager.findUserEventsByTimeAndIds(
				startTime, endTime, userId);
		map.put("events", events);

		return "/event/projectManager";
	}

	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/event/findEvents")
	public String getEventDetailsInSomeDay(HttpServletRequest request,
			HttpServletResponse response, ModelMap model) {

		try {
			String st = ServletRequestUtils.getStringParameter(request,
					"startTime");
			String et = ServletRequestUtils.getStringParameter(request,
					"endTime");

			if (st != null && et != null) {
			} else {
				Calendar start = Calendar.getInstance();
				start.set(Calendar.DAY_OF_MONTH, 1);
				Calendar end = Calendar.getInstance();
				end.set(Calendar.DAY_OF_MONTH,
						end.getActualMaximum(Calendar.DAY_OF_MONTH));

				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				st = sdf.format(start.getTime());
				et = sdf.format(end.getTime());
			}

			model.put("startTime", st);
			model.put("endTime", et);
			
			request.getSession().setAttribute("startTime", st);
			request.getSession().setAttribute("endTime", et);

			User u = (User) SecurityContextHolder.getContext()
					.getAuthentication().getPrincipal();
			List<EventTable> events = eventManager.findUserEventsByTime(st, et,
					u.getId());
			model.put("events", events);

			double totalHours = 0;
			for (EventTable eventTable : events) {
				totalHours += eventTable.getDuration();
			}
			model.put("totalHours", totalHours);

		} catch (ServletRequestBindingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return "/event/findEvents";
	}

	/**
	 * 
	 * @param request
	 * @param response
	 * @param name
	 * @param cmonth
	 * @param model
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	@RequestMapping(value = "/event/getMonthDetails")
	public String getEventDetailsByMonth(HttpServletRequest request,
			HttpServletResponse response, @RequestParam Long name,
			@RequestParam Integer cyear, @RequestParam Integer cmonth, Map model) {
		if (name == null || cyear == 0 || cmonth == 0) {

		} else {
			List<EventTable> list = eventManager.getEventByMonth(cyear, cmonth,
					name);

			request.setAttribute("events", list);
		}

		return "/event/getMonthDetails";
	}

	/**
	 * 约会的详细信息
	 * 
	 * @param request
	 * @param response
	 * @param id
	 * @param model
	 * @return
	 * @throws ServletRequestBindingException
	 */
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/event/getEventInfo")
	public String getEventDetailsInfo(HttpServletRequest request,
			HttpServletResponse response, @RequestParam Integer id,
			@SuppressWarnings("rawtypes") Map model)
			throws ServletRequestBindingException {

		String from = ServletRequestUtils.getStringParameter(request, "from");

		if (StringUtils.isBlank(from)) {
			from = "/event/findEvents.html";
		}
		model.put("from", from);

		if (id > 0) {
			EventTable et = this.eventManager.getEventWithAttachments(id);

			if (et != null) {
				request.setAttribute("event", et);
				Set<AttachmentTable> ats = et.getAttachmentTables();
				request.setAttribute("attachments", ats);
			} else {
				this.saveError(request,
						getText("event.info.not.exist", request.getLocale()));
			}
		} else {
			this.saveError(request,
					getText("event.info.not.exist", request.getLocale()));
		}
		return "/event/getEventInfo";
	}

	/**
	 * 下载附件
	 * 
	 * @param request
	 * @param response
	 * @param id
	 */
	@RequestMapping(value = "/event/attachment")
	public void getAttachment(HttpServletRequest request,
			HttpServletResponse response, @RequestParam("id") Integer id) {

		if (id != null && id > 0) {
			AttachmentTable att = this.eventManager.getAttachmentTableById(id);
			String uri = att.getFileUri();
			String path = request.getSession().getServletContext()
					.getRealPath("/upload/" + uri);
			File f = new File(path);

			FileInputStream in = null;
			try {
				response.setContentType("application/octet-stream");
				response.setHeader("Content-Disposition",
						"attachment;filename=" + att.getSourceName());
				in = new FileInputStream(f);
				IOUtils.copy(in, response.getOutputStream());
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				IOUtils.closeQuietly(in);
			}
		}
	}

	public void setEventManager(EventManager eventManager) {
		this.eventManager = eventManager;
	}

	public void setBudgetManager(BudgetManager budgetManager) {
		this.budgetManager = budgetManager;
	}

}
